#include <lpc2292.h>
#include <SysTimer_driver.h>
#include <Defs.h>

#define VIC_TIMER0_bit (1 << VIC_TIMER0)
#define VIC_TIMER1_bit (1 << VIC_TIMER1)

static volatile uint __systime0 = 0;
static volatile byte _t1ForKeyboard = true;
static void (*extHandlerKey)(void);
static void (*extHandlerADC)(void);

//Interrupt handler for timer 0
static void innHandlerLCD(void)
{
    static volatile byte systime_clk = 0, lcd_clk = 0;

    systime_clk = (systime_clk + 1) & 0x03;
    if (!systime_clk) __systime0++;

    if (lcd_clk)
    {
        IO0SET |= P_12;
        lcd_clk = 0;
    }
    else
    {
        IO0CLR |= P_12;
        lcd_clk = 1;
    }

    T0IR = 0xff; // Clear timer 0 interrupt line.
}

//Interrupt handler for timer 1
static void timer1_interrupt(void)
{
	if(_t1ForKeyboard)
		(*extHandlerKey)(); //delegate for keyboard function
	else
		(*extHandlerADC)(); //delegate for ADC function
	
    T1IR = 0xff; // Clear timer 1 interrupt line.
}

//Initialize both timer 
void SysTInit(void (*externalHandlerForKeyboard)(void), void (*externalHandleForADC)(void))
{
	VICProtection = 0;

	VICIntSelect &= ~VIC_TIMER0_bit;		// IRQ on timer 0 line.
	VICVectAddr0 = (uint)&innHandlerLCD;
	VICVectCntl0 = 0x20 | VIC_TIMER0;		// Enable vector interrupt for timer 0.
	VICIntEnable |= VIC_TIMER0_bit;			// Enable timer 0 interrupt.

	T0TCR = 0;				// Disable timer 0.
							// The prescaler refuses any value other than zero!?
	T0PC  = 0;				// Prescaler is set to no division. Cclk is 48 MHz, pclk is 12 MHz.
	T0MR0 = COUNTER_4000Hz;	// Count up to this value. Generate 4000 Hz interrupt.
	T0MCR = INT_AND_RES_MR0;// Reset and interrupt on MR0 (match register 0).
	T0CCR = 0;				// Capture is disabled.
	T0EMR = 0;				// No external match output.

	VICIntSelect &= ~VIC_TIMER1_bit;		// IRQ on timer 1 line.
	VICVectAddr1 = (unsigned int)&timer1_interrupt;
	VICVectCntl1 = 0x20 | VIC_TIMER1;		// Enable vector interrupt for timer 1.
	VICIntEnable |= VIC_TIMER1_bit;			// Enable timer 1 interrupt.

	extHandlerKey = externalHandlerForKeyboard;
	extHandlerADC = externalHandleForADC;
	
	T1TCR = 0;										// Disable timer 1.
													// The prescaler refuses any value other than zero!?
	T1PC  = 0;										// Prescaler is set to no division. Cclk is 48 MHz, pclk is 12 MHz.
	T1MR0 = COUNTER_800Hz;							// Count up to this value. Generate 800 Hz interrupt.
	//T1MR1 = COUNTER_seconds(MAX_SIGNAL_DURATION);	// Count up to this value. Generate interrupt every MAX_SIGNAL_DURATION seconds.
	T1MR1 = COUNTER_1Hz/22050;						// Count up to this value. Generate 22050Hz interrupt.
	T1MCR = INT_AND_RES_MR0;						// Reset and interrupt on MR0 (match register 0).
	T1CCR = 0;										// Capture is disabled.
	T1EMR = 0;			
}

uint SysTms(void)
{
	return __systime0;
}

uint SysTmsDelta(uint t)
{
    return SysTms() - t;
}

void SysTmsDelay(uint ms)
{
    uint t = SysTms();

	while (1)
		if (SysTmsDelta(t) > ms) 
			break;
}

//Change vector for timer 1
void SysTChangeVectorT1(void)
{
	if(_t1ForKeyboard)
	{
		SysTStopTimer1();
		SysTResetTimer1();
		T1MCR = INT_AND_RES_MR1;
		_t1ForKeyboard = false;
		SysTStartTimer1();
	}
	else
	{
		SysTStopTimer1();
		SysTResetTimer1();
		T1MCR = INT_AND_RES_MR0;
		_t1ForKeyboard = true;
	}
}





